//
//  XLSampleDataProvider.m
//  AudioWaveDemo
//
//  Created by ilongge on 2023/4/17.
//

#import "XLSampleDataProvider.h"
#import <AVFoundation/AVFoundation.h>
#import <UIKit/UIKit.h>

@interface XLSampleDataProvider()

@end

@implementation XLSampleDataProvider

+ (void)loadAudioSampleFromAsset:(AVAsset *)asset completionBlock:(void(^)(NSData *, NSInteger))completionBlock
{
    NSString *tracks = @"tracks";
    [asset loadValuesAsynchronouslyForKeys:@[tracks]
                         completionHandler:^{
        AVKeyValueStatus status = [asset statusOfValueForKey:tracks error:nil];
        NSData *sampleData = nil;
        if (status == AVKeyValueStatusLoaded){
            sampleData = [self readAudioSamplesFromAsset:asset samplesBlock:nil];
        }
        CMTime time = asset.duration;
        NSInteger duration = (NSInteger)(((float)time.value / (float)time.timescale) * 1000);
        dispatch_async(dispatch_get_main_queue(), ^{
            completionBlock(sampleData, duration);
        });
    }];
}

+ (void)loadAudioSampleFromAsset:(AVAsset *)asset samplesBlock:(BOOL (^)(NSData *, BOOL))samplesBlock
{
    NSString *tracks = @"tracks";
    [asset loadValuesAsynchronouslyForKeys:@[tracks]
                         completionHandler:^{
        AVKeyValueStatus status = [asset statusOfValueForKey:tracks error:nil];
        if (status == AVKeyValueStatusLoaded){
            [self readAudioSamplesFromAsset:asset samplesBlock:samplesBlock];
        }
    }];
}
+ (NSData *)readAudioSamplesFromAsset:(AVAsset *)asset samplesBlock:(BOOL (^)(NSData *, BOOL))samplesBlock
{
    NSError *error;
    AVAssetReader *assetReader = [[AVAssetReader alloc] initWithAsset:asset error:&error]; //创建读取
    if (error) {
        NSLog(@"%@", [error localizedDescription]);
        return nil;
    }
    
    NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeAudio];
    AVAssetTrack *track = [tracks firstObject];
    NSDictionary *outputSetting = @{AVFormatIDKey:@(kAudioFormatLinearPCM),
                                    AVLinearPCMIsBigEndianKey:@NO,
                                    AVLinearPCMIsFloatKey:@NO,
                                    AVLinearPCMBitDepthKey:@(16)};
    
    AVAssetReaderTrackOutput *trackOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:track outputSettings:outputSetting];
    [assetReader addOutput:trackOutput];
    [assetReader startReading];
    
    NSMutableData *sampleData;
    if (samplesBlock == nil){
        sampleData = [[NSMutableData alloc] init];
    }
    BOOL canNext = YES;
    while (assetReader.status == AVAssetReaderStatusReading) {
        CMSampleBufferRef  sampleBuffer = [trackOutput copyNextSampleBuffer];
        
        if (sampleBuffer) {
            CMBlockBufferRef blockBUfferRef = CMSampleBufferGetDataBuffer(sampleBuffer);
            size_t length = CMBlockBufferGetDataLength(blockBUfferRef);
            SInt16 sampleBytes[length];
            CMBlockBufferCopyDataBytes(blockBUfferRef, 0, length, sampleBytes);
            if (samplesBlock){
                sampleData = [[NSMutableData alloc] init];
                [sampleData appendBytes:sampleBytes length:length];
                canNext = samplesBlock(sampleData, NO);
            }
            else{
                [sampleData appendBytes:sampleBytes length:length];
            }
            CMSampleBufferInvalidate(sampleBuffer);
            CFRelease(sampleBuffer);
        }
    }
    if (samplesBlock ){
        samplesBlock(sampleData, YES);
    }
    if (assetReader.status != AVAssetReaderStatusCompleted) {
        NSLog(@"获取音频数据失败");
        return nil;
    }
    return sampleData;
} 

@end
